<template>
  <div class="login_container">
    <div class="login_box">
      <!-- 头像 -->
      <div class="avatar_box">
        <img src="../assets/logo.png" alt="" />
      </div>
<!--登陆表单
1.为el-form添加 :model数据绑定指向一个数据对象，在表单中填写的数据都会自动同步到forms对象上，form对象在data中定义；
2.为每一个表单项的文本输入框（input）通过v-model属性绑定到数据对象对应的具体属性中（如v-model="form.name"绑定到form的name属性上）
3.为表单添加验证规则：3.1.首先为el-form组件绑定一个rules属性，值rules为表单验证规则对象；
                    3.2.在data数据中定义验证对象，每一个属性比如name等都是验证规则，验证规则一般都是数组，数组中的每一个对象都是验证规则；如required:true(必填项)，
                   message:"请输入.."(如果不符合规则将显示请输入...) trigger:'blur'(鼠标失去焦点时触发验证行为)
                   3.3.为每一个item指定prop属性等于具体的验证规则(表示希望用如prop="name"的验证规则验证下边el-input表单数据项)
4.实现重置表单  4.1.获取表单实例对象,加ref引用,此时loginFormRef就是表单实例对象,可直接通过它直接调用resetField函数重置表单;
               4.2.为"重置"按钮绑定点击事件实现点击“重置”按钮重置表单,调用resetField方法(打印this展示当前组件实例,可通过this.$refs获取loginFormRef,
               loginFormRef又为引用对象，即组件实例，接着可直接通过引用对象调用重置表单函数)
5.登录前(表单)的预验证  点击登录按钮,不应该直接发起登录的网络请求,而应该先对表单数据预验证,只有验证通过后才允许发起网络请求,否则直接提示用户表单数据不合法,
                 怎么进行预验证？点击登录时,通过调用表单的某个函数进行预验证,通过表单的引用对象(refs值)调用validate
                 5.1.为“登录”按钮绑定点击事件,先获取表单实例对象,调用validate函数检验(检验函数validate接受一个回调函数(callback),回调函数第一个形参是boolean值代表验证结果,根据true(验证通过)/false(验证失败))
                 5.2.根据验证结果判断是否发起请求
                 if判断 valid为false时直接return阻止请求;
                      valid为true时要发起请求,即要用axios(配置axios：1.导入axios包，2.将包挂载到vue原型 3.配置根路径)
                 axios配置完后，this.$http可以发起请求,根据api接口知,请求地址是login,请求方法是post,同时要携带username和password这两个参数;
                 past返回值是promise,用await和async简化promise操作(await只能用在被async修饰的方法中(即将await外边的箭头函数修饰成异步函数)),
                 然后直接拿到服务器返回的数据(包含6个属性),其中data为服务器返回的真实数据,从数据对象上解构赋值出data重命名为res对象
                 5.3. 判断是否登陆成功  根据res的meta属性的status是否等于200判断是否登录成功
6.登陆组件配置弹窗显示(显示用户登录成功与失败)-----message消息提示(不同状态)
                 6.1 导入message弹框组件，挂载在vue原型上，这样其他组件都可以直接this.$message调用
                6.2 直接调用message方法比如success()成功、error()失败 就可以弹出对应的框
7.登陆成功后的行为 7.1 将登陆成功后的token保存在客户端的sessionStorage中
                     (保存token到sessionStorage:window.sessionStorage.setItem('token', res.data.token))
                    7.1.1  项目中除了登录之外的其他api接口必须在登录之后才能访问
                    为什么保存token？  因为项目中除了登录之外的其他api接口必须在登录之后才能访问；
                    如果要访问其他接口，怎么才能告诉它我已经登录成功了哪？我们可以在访问这些接口时给他们提供token，
                    因为token是登录后服务器给我们身份认证，只要我们访问这些接口时携带token就可以访问成功，因为我们有必要将token保存在客户端中
                    7.1.2 token 只应在当前网站打开期间生效，所以必须将token保存在sessionStorage中
                    为什么token保存在sessionStorage中而不是localStorage中？
                    因为localStorage是持久化的存储机制，sessionStorage是会话期间的存储机制
                 7.2 通过编程式导航跳转到后台主页，路由地址是'/home' 访问到了home组件  this.$router.push('/home')
                 1. 创建home组件  2.home组件导入路由规则中
                 转入router路由导航守卫
                 -->

      <el-form ref="loginFormRef" :model="loginForm" :rules="loginFormRules" label-width="0px" class="login_form">
        <!-- 用户名 图标或直接用el-icon-s-custom-->
        <!-- 可参考input带icon的输入框 -->
        <el-form-item prop="username">
          <el-input v-model="loginForm.username" prefix-icon="iconfont icon-user"></el-input>
        </el-form-item>
        <!-- 密码  图标或直接用el-icon-lock   type="password"密码隐藏 -->
        <el-form-item prop="password">
          <el-input v-model="loginForm.password" prefix-icon="iconfont icon-3702mima"
          type="password"></el-input>
        </el-form-item>
        <!-- 按钮 -->
        <el-form-item class="btns">
         <el-button type="primary" @click="login">登录</el-button>
         <el-button type="info" @click="resetLoginForm">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      // 登陆表单的数据绑定对象
      loginForm: {
        username: 'admin',
        password: '123456'
      },
      // 表单验证规则对象
      loginFormRules: {
        // 验证用户名是否合法
        username: [
          { required: true, message: '请输入登录名称', trigger: 'blur' },
          { min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' }
        ],
        // 验证密码是否合法
        password: [
          { required: true, message: '请输入登录密码', trigger: 'blur' },
          { min: 6, max: 15, message: '长度在 6 到 15 个字符', trigger: 'blur' }
        ]

      }

    }
  },
  methods: {
    // 点击重置按钮，重置登陆表单  打印this展示当前组件实例,可通过this.$refs获取loginFormRef,
    // loginFormRef又为引用对象，即组件实例，接着可直接通过引用对象调用重置表单函数
    resetLoginForm (loginFormRef) {
      this.$refs['loginFormRef'].resetFields()
      // this.$refs.loginFormRef.resetFields()
    },
    login () {
      this.$refs.loginFormRef.validate(async valid => {
        // console.log(111)
        // console.log(valid)
        if (!valid) return
        // this.$http发起请求,post请求方式,请求地址为login,username和password这两个请求参数可直接用loginForm代替
        // 用const result接收,先console.log(result)打印一下,结果为promise;
        // 注：如果某个方法的返回值是promise,可以用await和async简化promise操作,可以在this之前加await,但await只能用在被async修饰的方法中,
        // 我们应该将紧挨着await的方法修饰成异步async方法(即将箭头函数变成异步函数),此时再打印不再是promise,而是一个具体响应对象(6个属性),其中data是服务器返回的数据;
        // 将data属性解构赋值出来重命名为res,将result变成{data:res},即可直接访问服务器数据(只剩下data属性)
        const { data: res } = await this.$http.post('login', this.loginForm)
        // console.log(res)
        if (res.meta.status !== 200) return this.$message.error('登陆失败')
        this.$message.success('登录成功')
        // console.log('res')
        // res的data中有一个token   保存token到sessionStorage
        window.sessionStorage.setItem('token', res.data.token)
        // 编程式导航跳转到后台主页'/home'
        this.$router.push('/home')
      })
    }

  }
}

</script>

<style lang="less" scoped>
.login_container {
  background-color: #2b4b6b;
  // 让背景色沾满全屏，右键发现需要让html、body、id为app沾满全屏，在assets中新建css-global,全局样式表需要导入入口文件main.js才可生效
  //此时html、body、id为app沾满全屏,但div为.login_container没有，需要设置高度100%
  height: 100%; /* 设置div为.login_container高度100%，沾满全屏 */
  display: flex; /* flex盒子剧中 */
  justify-content: center;
  align-items: center;
}
.login_box {
  width: 450px;
  height: 300px;
  background-color: #fff;
  border-radius: 3px;
  display: flex; /* flex盒子剧中 */
  justify-content: center;

  .avatar_box {
    width: 130px;
    height: 130px;
    border: 1px solid #eee;
    border-radius: 50%;
    padding: 10px;
    box-shadow: 0 0 10px #ddd;
    margin-top: -70px; /* 向上移动 */
    background-color: #fff;

    img {
      width: 100%; /* 让图片等于副盒子avatar_box的宽高 */
      height: 100%;
      border-radius: 50%;
      border-color: #eee;
    }
  }
}
.login_form {
  position: absolute;
  bottom: 130px;
  width:33%;
  padding: 0 20px;
  box-sizing: border-box;

}
.btns {
  display: flex;
  justify-content: flex-end;
}
</style>
